package com.ruoyi.file.service.storage.impl.tencent;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.file.domain.SysStorageConfig;
import com.ruoyi.file.enums.StorageTypeEnum;
import com.ruoyi.file.service.storage.base.BaseS3StorageServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * 腾讯云COS存储服务实现
 * 
 * @author ruoyi
 */
@Slf4j
@Service("tencentCosStorageService")
public class TencentCosStorageServiceImpl extends BaseS3StorageServiceImpl {

    @Override
    protected StorageTypeEnum getStorageType() {
        return StorageTypeEnum.TENCENT;
    }

    @Override
    public boolean shouldUsePathStyle() {
        return false; // 腾讯云COS 使用虚拟主机风格
    }

    @Override
    protected boolean shouldSetContentType() {
        return false; // 腾讯云COS 不预设置content-type，避免签名不匹配
    }

    @Override
    protected String buildFileUrl(String protocol, String endpoint, String bucketName, String filePath, StorageTypeEnum storageType) {
        // 腾讯云COS使用虚拟主机风格: bucket.endpoint/filePath
        return String.format("%s://%s.%s/%s", protocol, bucketName, endpoint, filePath);
    }

    /**
     * 重写创建桶方法，验证腾讯云COS桶名格式
     */
    @Override
    public boolean createBucket(String bucketName, SysStorageConfig config) {
        // 验证桶名格式 - 腾讯云COS要求桶名格式为：bucketname-appid
        if (StringUtils.isBlank(bucketName)) {
            throw new ServiceException("桶名称不能为空");
        }
        
        // 检查是否包含APPID格式（以-10位数字结尾）
        if (!bucketName.matches(".*-\\d{10}$")) {
            throw new ServiceException("腾讯云COS桶名称格式错误。正确格式为：桶名-APPID（如：mybucket-1234567890）。请输入完整的桶名称，包含您的10位数字APPID");
        }
        
        try {
            // 直接使用用户输入的桶名（已包含APPID）
            return super.createBucket(bucketName, config);
        } catch (Exception e) {
            // 检查是否是403 Access Denied错误，通常表示APPID错误或权限不足
            if (e.getMessage() != null && e.getMessage().contains("Access Denied")) {
                String appId = bucketName.substring(bucketName.lastIndexOf("-") + 1);
                throw new ServiceException("创建腾讯云COS存储桶失败：访问被拒绝。请检查：\n" +
                        "1. APPID（" + appId + "）是否正确\n" +
                        "2. AccessKey和SecretKey是否正确\n" +
                        "3. 当前账户是否有创建存储桶的权限\n" +
                        "4. 该桶名是否已被其他用户占用");
            }
            // 重新抛出其他异常
            throw e;
        }
    }


    /**
     * 腾讯云COS特殊的CORS配置
     * 重写父类方法以提供更适合腾讯云的CORS配置
     */
    @Override
    public boolean configureBucketCors(String bucketName, com.ruoyi.file.domain.SysStorageConfig config) {
        try (software.amazon.awssdk.services.s3.S3Client s3Client = createS3Client(config)) {
            // 腾讯云COS的CORS配置
            software.amazon.awssdk.services.s3.model.CORSRule corsRule = software.amazon.awssdk.services.s3.model.CORSRule.builder()
                    .allowedHeaders("*")
                    .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD")
                    .allowedOrigins("*") // 生产环境建议改为具体域名
                    .maxAgeSeconds(3600)
                    .exposeHeaders("ETag", "Content-Length", "Date")
                    .build();

            software.amazon.awssdk.services.s3.model.CORSConfiguration corsConfiguration = 
                software.amazon.awssdk.services.s3.model.CORSConfiguration.builder()
                    .corsRules(java.util.Collections.singletonList(corsRule))
                    .build();

            software.amazon.awssdk.services.s3.model.PutBucketCorsRequest corsRequest = 
                software.amazon.awssdk.services.s3.model.PutBucketCorsRequest.builder()
                    .bucket(bucketName)
                    .corsConfiguration(corsConfiguration)
                    .build();

            s3Client.putBucketCors(corsRequest);
            
            return true;
        } catch (Exception e) {
            log.error("配置腾讯云COS存储桶CORS失败: bucketName={}, error={}", bucketName, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 重写获取CORS状态方法，提供更详细的腾讯云COS状态信息
     */
    @Override
    public String getBucketCors(String bucketName, com.ruoyi.file.domain.SysStorageConfig config) {
        try (software.amazon.awssdk.services.s3.S3Client s3Client = createS3Client(config)) {
            software.amazon.awssdk.services.s3.model.GetBucketCorsRequest corsRequest = 
                software.amazon.awssdk.services.s3.model.GetBucketCorsRequest.builder()
                    .bucket(bucketName)
                    .build();

            software.amazon.awssdk.services.s3.model.GetBucketCorsResponse response = s3Client.getBucketCors(corsRequest);
            
            if (response.corsRules() != null && !response.corsRules().isEmpty()) {
                software.amazon.awssdk.services.s3.model.CORSRule rule = response.corsRules().get(0);
                // 将枚举转换为字符串
                java.util.List<String> methods = rule.allowedMethods().stream()
                    .map(Object::toString)
                    .collect(java.util.stream.Collectors.toList());
                
                // 检查是否包含所有必要的方法和头部
                boolean hasAllMethods = methods.containsAll(java.util.Arrays.asList("PUT", "POST", "GET", "DELETE", "HEAD", "OPTIONS"));
                boolean hasWildcardHeaders = rule.allowedHeaders() != null && rule.allowedHeaders().contains("*");
                boolean hasWildcardOrigins = rule.allowedOrigins() != null && rule.allowedOrigins().contains("*");
                
                String status = String.format("腾讯云COS CORS已配置 - 方法: %s, 来源: %s, 头部: %s", 
                    String.join(",", methods), 
                    String.join(",", rule.allowedOrigins() != null ? rule.allowedOrigins() : java.util.Collections.emptyList()),
                    rule.allowedHeaders() != null ? String.join(",", rule.allowedHeaders()) : "无");
                
                if (hasAllMethods && hasWildcardHeaders && hasWildcardOrigins) {
                    return status + " ✓ 配置完整，支持前端直传";
                } else {
                    return status + " ⚠ 配置不完整，可能影响前端直传";
                }
            }
            
            return "腾讯云COS未配置CORS";
        } catch (Exception e) {
            log.warn("获取腾讯云COS存储桶CORS配置失败: {}", e.getMessage());
            if (e.getMessage() != null && e.getMessage().contains("does not exist")) {
                return "腾讯云COS未配置CORS - 需要配置后才能支持前端直传";
            }
            return "获取腾讯云COS CORS配置失败: " + e.getMessage();
        }
    }
}
